home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / utils / arepdaem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-31  |  17.7 KB  |  666 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: arepdaem.c,v 5.12 1993/05/31 19:39:24 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.12 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1988-1992 USENET Community Trust
  8.  *             Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: arepdaem.c,v $
  17.  * Revision 5.12  1993/05/31  19:39:24  syd
  18.  * check for missing replyfile
  19.  * From: roy@lorien.gatech.edu (Roy Mongiovi)
  20.  *
  21.  * Revision 5.11  1993/02/03  20:18:52  syd
  22.  * with unistd being included now, setpgrp complains about
  23.  * calling sequence errors, force appropriate type.
  24.  * From: Syd
  25.  *
  26.  * Revision 5.10  1993/01/20  03:37:16  syd
  27.  * Nits and typos in the NLS messages and corresponding default messages.
  28.  * From: dwolfe@pffft.sps.mot.com (Dave Wolfe)
  29.  *
  30.  * Revision 5.9  1992/12/11  01:45:04  syd
  31.  * remove sys/types.h include, it is now included by defs.h
  32.  * and this routine includes defs.h or indirectly includes defs.h
  33.  * From: Syd
  34.  *
  35.  * Revision 5.8  1992/12/07  04:21:58  syd
  36.  * add missing err declares
  37.  * From: Syd
  38.  *
  39.  * Revision 5.7  1992/12/07  03:00:27  syd
  40.  * Fix long -> time_t
  41.  * From: Syd
  42.  *
  43.  * Revision 5.6  1992/11/26  00:46:50  syd
  44.  * Fix how errno is used so err is inited and used instead
  45.  * as errno gets overwritten by print system call
  46.  * From: Syd
  47.  *
  48.  * Revision 5.5  1992/11/07  20:05:52  syd
  49.  * change to use header_cmp to allow for linear white space around the colon
  50.  * From: Syd
  51.  *
  52.  * Revision 5.4  1992/10/27  01:43:40  syd
  53.  * Move posix_signal to lib directory
  54.  * From: tom@osf.org
  55.  *
  56.  * Revision 5.3  1992/10/25  02:54:00  syd
  57.  * add posix signal stuff as stop gap, needs to be moved to lib
  58.  * From: syd
  59.  *
  60.  * Revision 5.2  1992/10/11  00:59:39  syd
  61.  * Fix some compiler warnings that I receive compiling Elm on my SVR4
  62.  * machine.
  63.  * From: Tom Moore <tmoore@fievel.DaytonOH.NCR.COM>
  64.  *
  65.  * Revision 5.1  1992/10/04  00:46:45  syd
  66.  * Initial checkin as of 2.4 Release at PL0
  67.  *
  68.  *
  69.  ******************************************************************************/
  70.  
  71. /** Keep track of mail as it arrives, and respond by sending a 'recording'
  72.     file to the sender as new mail is received.
  73.  
  74.     Note: the user program that interacts with this program is the
  75.     'autoreply' program and that should be consulted for further
  76.     usage information.
  77.  
  78.     This program is part of the 'autoreply' system, and is designed
  79.     to run every hour and check all mailboxes listed in the file 
  80.     "/etc/autoreply.data", where the data is in the form:
  81.  
  82.     username    replyfile    current-mailfile-size
  83.  
  84.     To avoid a flood of autoreplies, this program will NOT reply to mail 
  85.     that contains header "X-Mailer: fastmail".  Further, each time the 
  86.     program responds to mail, the 'mailfile size' entry is updated in
  87.     the file /etc/autoreply.data to allow the system to be brought 
  88.     down and rebooted without any loss of data or duplicate messages.
  89.  
  90.     This daemon also uses a lock semaphore file, /usr/spool/uucp/LCK..arep,
  91.     to ensure that more than one copy of itself is never running.  For this
  92.     reason, it is recommended that this daemon be started up each morning
  93.     from cron, since it will either start since it's needed or simply see
  94.     that the file is there and disappear.
  95.  
  96.     Since this particular program is the main daemon answering any
  97.     number of different users, it must be run with uid root.
  98. **/
  99.  
  100. #include "elmutil.h"
  101. #include "s_arepdaem.h"
  102.  
  103. #ifdef BSD
  104. # include <sys/time.h>
  105. #else
  106. # include <time.h>
  107. #endif
  108.  
  109. #include <sys/stat.h>
  110. #include <ctype.h>
  111. #include <errno.h>
  112.  
  113. #define arep_lock_file    "LCK..arep"
  114.  
  115. #define autoreply_file    "/etc/autoreply.data"
  116.  
  117. #define logfile        "/etc/autoreply.log"    /* first choice   */
  118. #define logfile2    "/tmp/autoreply.log"    /* second choice  */
  119.  
  120. #define BEGINNING    0        /* see fseek(3S) for info */
  121. #define SLEEP_TIME    3600        /* run once an hour       */
  122. #define MAX_PEOPLE    20        /* max number in program  */
  123.  
  124. #define EXISTS        00        /* lock file exists??     */
  125.  
  126. #define remove_return(s)    if (strlen(s) > 0) { \
  127.                       if (s[strlen(s)-1] == '\n') \
  128.                     s[strlen(s)-1] = '\0'; \
  129.                         }
  130.  
  131. struct replyrec {
  132.     char     username[NLEN];        /* login name of user */
  133.     char    mailfile[SLEN];        /* name of mail file  */
  134.     char    replyfile[SLEN];    /* name of reply file */
  135.     long    mailsize;        /* mail file size     */
  136.     int     in_list;        /* for new replies    */
  137.       } reply_table[MAX_PEOPLE];
  138.  
  139. FILE  *logfd;                /* logfile (log action)   */
  140. time_t autoreply_time = 0L;        /* modif date of autoreply file */
  141. int   active = 0;            /* # of people 'enrolled' */
  142.  
  143. static char    *def_subj,        /* Default subject text              */
  144.         *subj_fw,        /* First word of subject             */
  145.         *arep_subj;        /* Autorepysubject with subject text */
  146.  
  147. FILE  *open_logfile();            /* forward declaration    */
  148.  
  149. long  bytes();                /*       ditto           */
  150. time_t ModTime();            /*       ditto          */
  151. void read_autoreply_file();
  152.  
  153. SIGHAND_TYPE    term_signal();
  154.  
  155. extern int errno;    /* system error number! */
  156.  
  157. main()
  158. {
  159.     long size;
  160.     int  person, data_changed;
  161.     time_t last_mod_time;
  162.  
  163.     if (fork()) exit(0);
  164.  
  165.     if (! lock())
  166.       exit(0);    /* already running! */
  167.  
  168.     signal(SIGTERM, term_signal);     /* Terminate signal         */
  169.  
  170. #ifdef BSD
  171.     person = getpid();
  172.     setpgrp(person, person);
  173. #else
  174.     setpgrp();
  175. #endif
  176.  
  177. #ifdef I_LOCALE
  178.     setlocale(LC_ALL, "");
  179. #endif
  180.  
  181.     elm_msg_cat = catopen("elm2.4", 0);
  182.  
  183.     /* Get the subject texts */
  184.  
  185.     def_subj = catgets(elm_msg_cat, ArepdaemSet, ArepdaemDefSubj,
  186.       "Auto-reply Mail");
  187.     subj_fw = catgets(elm_msg_cat, ArepdaemSet, ArepdaemSubjFw,
  188.       "Auto-reply");
  189.     arep_subj = catgets(elm_msg_cat, ArepdaemSet, ArepdaemArepSubj,
  190.       "Auto-reply to:%s");
  191.  
  192.     while (1) {
  193.  
  194.       logfd = open_logfile();    /* open the log */
  195.  
  196.       /* 1. check to see if autoreply table has changed.. */
  197.  
  198.       if ((last_mod_time = ModTime(autoreply_file)) != autoreply_time) {
  199.         read_autoreply_file(); 
  200.         autoreply_time = last_mod_time;
  201.       }
  202.  
  203.       /* 2. now for each active person... */
  204.     
  205.       data_changed = 0;
  206.  
  207.       for (person = 0; person < active; person++) {
  208.         if (access(reply_table[person].replyfile, READ_ACCESS) == -1)
  209.         {
  210.            log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemRemovingUser,
  211.          "removing %s from the active list"),
  212.               reply_table[person].username);
  213.            strcpy(reply_table[person].username, 
  214.               reply_table[active-1].username);
  215.            strcpy(reply_table[person].mailfile, 
  216.               reply_table[active-1].mailfile);
  217.            strcpy(reply_table[person].replyfile, 
  218.               reply_table[active-1].replyfile);
  219.            reply_table[person].mailsize = reply_table[active-1].mailsize;
  220.            active--;
  221.            data_changed++;
  222.         }
  223.         else
  224.            if ((size = bytes(reply_table[person].mailfile)) != reply_table[person].mailsize) {
  225.           if (size > reply_table[person].mailsize)
  226.              read_newmail(person);
  227.           /* else mail removed - resync */
  228.           reply_table[person].mailsize = size;
  229.           data_changed++;
  230.          }
  231.       }
  232.  
  233.       /* 3. if data changed, update autoreply file */
  234.  
  235.       if (data_changed)
  236.         update_autoreply_file();
  237.  
  238.       close_logfile();        /* close the logfile again */
  239.  
  240.       /* 4. Go to sleep...  */
  241.  
  242.       sleep(SLEEP_TIME);
  243.     }
  244. }
  245.  
  246. void
  247. read_autoreply_file()
  248. {
  249.     /** We're here because the autoreply file has changed!!  It
  250.         could either be because someone has been added or because
  251.         someone has been removed...since the list will always be in
  252.         order (nice, eh?) we should have a pretty easy time of it...
  253.     **/
  254.  
  255.     FILE *file;
  256.     char username[SLEN],     replyfile[SLEN];
  257.     int  person;
  258.      long size;
  259.     
  260.     log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemDataFileChange,
  261.       "Autoreply data file has changed!  Reading..."));
  262.  
  263. /*
  264.  * clear old entries prior to reread
  265.  */
  266.     for (person = 0; person < active; person++)
  267.       reply_table[person].in_list = 0;
  268.  
  269.     if ((file = fopen(autoreply_file,"r")) == NULL) {
  270.       log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemNoOne,
  271.         "No-one is using autoreply..."));
  272.     } else {
  273.       while (fscanf(file, "%s %s %dl", username, replyfile, &size) != EOF) {
  274.         /* check to see if this person is already in the list */
  275.         if ((person = in_reply_list(username)) != -1) {
  276.           reply_table[person].in_list = 1;
  277.           reply_table[person].mailsize = size;     /* sync */
  278.         }
  279.         else {     /* if not, add them */
  280.           if (active == MAX_PEOPLE) {
  281.         unlock();
  282.         exit(log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemMaxPeople,
  283.           "Couldn't add %s - already at max people!"), 
  284.                username));
  285.           }
  286.           log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemAddingUser,
  287.         "adding %s to the active list"), username);
  288.           strcpy(reply_table[active].username, username);
  289.           sprintf(reply_table[active].mailfile, "%s%s", mailhome, username);
  290.           strcpy(reply_table[active].replyfile, replyfile);
  291.           reply_table[active].mailsize = size;
  292.           reply_table[active].in_list = 1;    /* obviously! */
  293.           active++;
  294.         }
  295.       }
  296.       fclose(file);
  297.     }
  298.  
  299.     /** now check to see if anyone has been removed... **/
  300.  
  301.     person = 0;
  302.     while (person < active)
  303.       if (reply_table[person].in_list && access(reply_table[person].replyfile, READ_ACCESS) == 0) {
  304.         person++;
  305.       }
  306.       else {
  307.         log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemRemovingUser,
  308.           "removing %s from the active list"),
  309.            reply_table[person].username);
  310.         strcpy(reply_table[person].username, 
  311.            reply_table[active-1].username);
  312.         strcpy(reply_table[person].mailfile, 
  313.            reply_table[active-1].mailfile);
  314.         strcpy(reply_table[person].replyfile, 
  315.            reply_table[active-1].replyfile);
  316.         reply_table[person].mailsize = reply_table[active-1].mailsize;
  317.         active--;
  318.       }
  319. }
  320.  
  321. update_autoreply_file()
  322. {
  323.     /** update the entries in the autoreply file... **/
  324.  
  325.     FILE *file;
  326.     register int person;
  327.  
  328.     if ((file = fopen(autoreply_file,"w")) == NULL) {
  329.       log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemErrUpdate,
  330.         "Couldn't update autoreply file!"));
  331.       return;
  332.     }
  333.  
  334.     for (person = 0; person < active; person++)
  335.       fprintf(file, "%s %s %ld\n",
  336.           reply_table[person].username,
  337.           reply_table[person].replyfile,
  338.           reply_table[person].mailsize);
  339.  
  340.     fclose(file);
  341.  
  342.     autoreply_time = ModTime(autoreply_file);
  343. }
  344.  
  345. int
  346. in_reply_list(name)
  347. char *name;
  348. {
  349.     /** search the current active reply list for the specified username.
  350.         return the index if found, or '-1' if not. **/
  351.  
  352.     register int iindex;
  353.  
  354.     for (iindex = 0; iindex < active; iindex++)
  355.       if (strcmp(name, reply_table[iindex].username) == 0)
  356.         return(iindex);
  357.     
  358.     return(-1);
  359. }
  360.  
  361. read_newmail(person)
  362. int person;
  363. {
  364.     /** Read the new mail for the specified person. **/
  365.  
  366.     
  367.     FILE *mailfile;
  368.     char from_whom[SLEN], subject[SLEN];
  369.     int  sendit;
  370.  
  371.     log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemNewMail,
  372.       "New mail for %s"), reply_table[person].username);
  373.  
  374.         if ((mailfile = fopen(reply_table[person].mailfile,"r")) == NULL)
  375.            return(log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemErrOpen,
  376.          "can't open mail file for user %s"),
  377.         reply_table[person].username));
  378.  
  379.         if (fseek(mailfile, reply_table[person].mailsize, BEGINNING) == -1) {
  380.        fclose(mailfile);
  381.            return(log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemErrSeek,
  382.          "couldn't seek to %ld in mail file!"),
  383.            reply_table[person].mailsize));
  384.     }
  385.  
  386.     while (get_return(mailfile, person, from_whom, subject, &sendit) != -1)
  387.       if (sendit)
  388.         reply_to_mail(person, from_whom, subject);
  389.  
  390.     fclose(mailfile);
  391.     return;
  392. }
  393.  
  394. int
  395. get_return(file, person, from, subject, sendit)
  396. FILE *file;
  397. int  person, *sendit;
  398. char *from, *subject;
  399. {
  400.     /** Reads the new message and return the from and subject lines.
  401.         sendit is set to true iff it isn't a machine generated msg
  402.  
  403.         If USE_EMBEDDED_ADDRESSES is set, then the return address
  404.         is taken as the last From: or Reply-To: that is seen in
  405.         the header lines.  Crude, but it works.
  406.     **/
  407.     
  408.     char name1[SLEN], name2[SLEN], lastname[SLEN];
  409.     char buffer[SLEN], hold_return[SLEN];
  410.     int done = 0, in_header = 0;
  411.  
  412.     from[0] = '\0';
  413.     name1[0] = '\0';
  414.     name2[0] = '\0';
  415.     lastname[0] = '\0';
  416.     *sendit = 1;
  417.  
  418.     while (! done) {
  419.  
  420.       if (fgets(buffer, SLEN, file) == NULL)
  421.     return(-1);
  422.  
  423. #ifndef USE_EMBEDDED_ADDRESSES
  424.       if (first_word(buffer, "From ")) {
  425.     in_header++;
  426.     sscanf(buffer, "%*s %s", hold_return);
  427.       }
  428.       else if (in_header) {
  429.         if (first_word_nc(buffer, ">From")) {
  430.       sscanf(buffer,"%*s %s %*s %*s %*s %*s %*s %*s %*s %s", name1, name2);
  431.       add_site(from, name2, lastname);
  432.         }
  433. #else /* We're allowing USE_EMBEDDED_ADDRESSES */
  434.       if (first_word(buffer, "From ")) 
  435.     in_header++;
  436.       else if (in_header) {
  437.     if (header_cmp(buffer, "From", NULL) ||
  438.         header_cmp(buffer, "Reply-To", NULL))
  439.       get_address_from(buffer, from);
  440. #endif
  441.         else if (header_cmp(buffer,"Subject", NULL)) {
  442.       remove_return(buffer);
  443.       strcpy(subject, (char *) (buffer + 8));
  444.         }
  445.         else if (header_cmp(buffer,"X-Mailer", "fastmail"))
  446.       *sendit = 0;
  447.         else if (strlen(buffer) == 1)
  448.       done = 1;
  449.       }
  450.     }
  451.  
  452. #ifndef USE_EMBEDDED_ADDRESSES
  453.     if (from[0] == '\0')
  454.       strcpy(from, hold_return); /* default address! */
  455.     else
  456.       add_site(from, name1, lastname);    /* get the user name too! */
  457. #endif
  458.  
  459.     return(0);
  460. }
  461.  
  462. reply_to_mail(person, from, subject)
  463. int   person;
  464. char *from, *subject;
  465. {
  466.     /** Respond to the message from the specified person with the
  467.         specified subject... **/
  468.     
  469.     char buffer[SLEN];
  470.  
  471.     if (strlen(subject) == 0)
  472.       strcpy(subject, def_subj);
  473.     else if (! first_word_nc(subject, subj_fw)) {
  474.       sprintf(buffer, arep_subj, subject);
  475.       strcpy(subject, buffer);
  476.     }
  477.  
  478.     log_msg(catgets(elm_msg_cat, ArepdaemSet, ArepdaemArepTo,
  479.       "auto-replying to '%s'"), from);
  480.  
  481.     mail(from, subject, reply_table[person].replyfile, person);
  482. }    
  483.  
  484. long
  485. bytes(name)
  486. char *name;
  487. {
  488.     /** return the number of bytes in the specified file.  This
  489.         is to check to see if new mail has arrived....  **/
  490.  
  491.     int ok = 1, err;
  492.     struct stat buffer;
  493.  
  494.     if (stat(name, &buffer) != 0)
  495.       if (errno != 2) {
  496.        err = errno;
  497.        unlock();
  498.        exit(MCfprintf(stderr, catgets(elm_msg_cat, ArepdaemSet,
  499.          ArepdaemErrFstat, "Error %d attempting fstat on %s"),
  500.            err, name));
  501.       }
  502.       else
  503.         ok = 0;
  504.     
  505.     return(ok ? buffer.st_size : 0);
  506. }
  507.  
  508. time_t
  509. ModTime(name)
  510. char *name;
  511. {
  512.     /** return the modification time in the specified file.
  513.         This is to check to see if autoreply has changed....  **/
  514.  
  515.     int ok = 1, err;
  516.     struct stat buffer;
  517.  
  518.     if (stat(name, &buffer) != 0)
  519.       if (errno != 2) {
  520.        err = errno;
  521.        unlock();
  522.        exit(MCfprintf(stderr, catgets(elm_msg_cat, ArepdaemSet,
  523.          ArepdaemErrFstat, "Error %d attempting fstat on %s"),
  524.            err, name));
  525.       }
  526.       else
  527.         ok = 0;
  528.  
  529.     return(ok ? buffer.st_mtime : (time_t) 0);
  530. }
  531.  
  532. mail(to, subject, filename, person)
  533. char *to, *subject, *filename;
  534. int   person;
  535. {
  536.     /** Mail 'file' to the user from person... **/
  537.     
  538.     char buffer[VERY_LONG_STRING];
  539.  
  540.     MCsprintf(buffer, catgets(elm_msg_cat, ArepdaemSet, ArepdaemMailCommand,
  541.       "%s/fastmail -f '%s [autoreply]' -s '%s' %s %s"),
  542.         BIN, reply_table[person].username,
  543.             subject, filename, to);
  544.     
  545.     system(buffer);
  546. }
  547.  
  548. log_msg(message, arg)
  549. char *message;
  550. char *arg;
  551. {
  552.     /** Put log entry into log file.  Use the format:
  553.           date-time: <message>
  554.     **/
  555.  
  556.     struct tm *thetime;
  557.     time_t      clock;
  558. #ifndef    _POSIX_SOURCE
  559.     struct tm *localtime(); 
  560.     time_t     time();
  561. #endif
  562.     char      buffer[SLEN];
  563.  
  564.     /** first off, get the time and date **/
  565.  
  566.     clock = time((time_t *) 0);       /* seconds since ???   */
  567.     thetime = localtime(&clock);    /* and NOW the time... */
  568.  
  569.     /** then put the message out! **/
  570.  
  571.     sprintf(buffer, message, arg);
  572.  
  573.     fprintf(logfd,"%d/%d-%d:%02d: %s\n", 
  574.         thetime->tm_mon+1, thetime->tm_mday,
  575.             thetime->tm_hour,  thetime->tm_min,
  576.             buffer);
  577. }
  578.  
  579. FILE *open_logfile()
  580. {
  581.     /** open the logfile.  returns a valid file descriptor **/
  582.  
  583.     FILE *fd;
  584.  
  585.     if ((fd = fopen(logfile, "a")) == NULL)
  586.       if ((fd = fopen(logfile2, "a")) == NULL) {
  587.         unlock();
  588.         exit(1);    /* give up! */
  589.       }
  590.  
  591.     return( (FILE *) fd);
  592. }
  593.  
  594. close_logfile()
  595. {
  596.     /** Close the logfile until needed again. **/
  597.  
  598.     fclose(logfd);
  599. }
  600.  
  601. /*** LOCK and UNLOCK - ensure only one copy of this daemon running at any
  602.      given time by using a file existance semaphore (wonderful stuff!) ***/
  603.  
  604. lock()
  605. {
  606.     char lock_name[SLEN];        /* name of lock file  */
  607.     char pid_buffer[SHORT];
  608.     int pid, create_fd, err;
  609.  
  610.     sprintf(lock_name, "%s/%s", LOCK_DIR, arep_lock_file);
  611. #ifdef PIDCHECK
  612.       /** first, try to read the lock file, and if possible, check the pid.
  613.       If we can validate that the pid is no longer active, then remove
  614.       the lock file.
  615.        **/
  616.     if((create_fd=open(lock_name,O_RDONLY)) != -1) {
  617.       if (read(create_fd, pid_buffer, SHORT) > 0) {
  618.         pid = atoi(pid_buffer);
  619.         if (pid) {
  620.           if (kill(pid, 0)) {
  621.             close(create_fd);
  622.             if (unlink(lock_name) != 0) {
  623.             err = errno;
  624.             MCprintf(catgets(elm_msg_cat, ArepdaemSet,
  625.             ArepdaemErrUnlink,
  626.             "Error %s\n\ttrying to unlink file %s (%s)\n"), 
  627.             error_description(err), lock_name, "lock");
  628.             return(0);
  629.             }
  630.           } else /* kill pid check succeeded */
  631.             return(0);
  632.         } else /* pid was zero */
  633.           return(0);
  634.       } else /* read failed */
  635.         return(0);
  636.     }
  637.     /* ok, either the open failed or we unlinked it, now recreate it. */
  638. #else
  639.     if (access(lock_name, EXISTS) == 0)
  640.       return(0);    /* file already exists */
  641. #endif
  642.  
  643.     if ((create_fd=creat(lock_name, 0444)) == -1)
  644.       return(0);    /* can't create file!!   */
  645.  
  646.     sprintf(pid_buffer,"%d\n", getpid() );        /* write the current pid to the file */
  647.     write(create_fd, pid_buffer, strlen(pid_buffer));
  648.     close(create_fd);                /* no need to keep it open */
  649.     
  650.     return(1);
  651.  
  652. }
  653.  
  654. unlock()
  655. {
  656.     /** remove lock file if it's there! **/
  657.  
  658.     (void) unlink(arep_lock_file);
  659. }
  660.  
  661. SIGHAND_TYPE    term_signal()
  662. {
  663.     unlock();
  664.     exit(1);    /* give up! */
  665. }
  666.